// Project: Salient
// http://salient.codeplex.com
// 
// Copyright 2010, Sky Sanders <sky at skysanders.net>
// Dual licensed under the MIT or GPL Version 2 licenses.
// http://salient.codeplex.com/license
// 
// Date: April 25 2010 

#region

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Management;
using Salient.Reflection;

#endregion

namespace Salient.Management
{
    /// <summary>
    /// Base class for WMI DTO classes. 
    /// Provides a WMI query factory method and base DTO loading capabilities.
    /// </summary>
    public abstract class WmiObject
    {
        /// <summary>
        /// Queries WMI and returns a list of loaded T
        /// <example>
        /// IList&lt;Win32Process> s = WMIObject.Query&lt;Win32Process>("Name='WebDev.WebServer.exe'");
        /// </example>
        /// </summary>
        public static IList<T> Query<T>(string filter) where T : WmiObject, new()
        {
            filter = (filter ?? string.Empty).Trim();

            filter = string.IsNullOrEmpty(filter) ? "" : " where " + filter;

            List<T> returnValue = new List<T>();
            string queryIdentifier = typeof (T).GetCustomAttribute<DescriptorAttribute>().Name;
            string query = string.Format(CultureInfo.InvariantCulture, "select * from {0} {1}", queryIdentifier, filter);

            using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
            {
                using (ManagementObjectCollection results = searcher.Get())
                {
                    foreach (ManagementObject process in results)
                    {
                        T proc = new T();
                        proc.Load(process);
                        process.Dispose();

                        returnValue.Add(proc);
                    }
                }
            }
            return returnValue;
        }


        /// <summary>
        /// Copies properties from a ManagementBaseObject to this instance using 
        /// the DescriptorAttribute for mapping information.
        /// </summary>
        public void Load(ManagementBaseObject source)
        {
            PropertyDescriptorCollection properties = GetType().GetCustomAttribute<DescriptorAttribute>().Properties;
            foreach (PropertyDescriptor prop in properties)
            {
                object value = prop.PropertyType.IsValueType ? Activator.CreateInstance(prop.PropertyType) : null;
                try
                {
                    value = Convert.ChangeType(source[prop.Name], prop.PropertyType);
                }
                    // ReSharper disable EmptyGeneralCatchClause
                catch
                    // ReSharper restore EmptyGeneralCatchClause
                {
                }
                prop.SetValue(this, value);
            }
        }
    }
}